<template>
  <div class="edit-wrapper"
       ref="editWrapperRef"
       @click="onItemClick(id)"
       :class="{active: active}"
       :style="styles"
       @mousedown="startMove"
       @keydown.enter="deleteItem"
  >
    <slot></slot>
    <div class="resizer-list">
      <div class='resizer top-left'  @mousedown.stop="startResize('top-left', $event)"></div>
      <div class='resizer top-right'  @mousedown.stop="startResize('top-right', $event)"></div>
      <div class='resizer bottom-left'  @mousedown.stop="startResize('bottom-left', $event)"></div>
      <div class='resizer bottom-right' @mousedown.stop="startResize('bottom-right', $event)"></div>
    </div>
  </div>
</template>

<script lang="ts">
import {computed, defineComponent, nextTick, ref} from 'vue'
import {pick} from "lodash-es";

export default defineComponent({
  name: "EditWrapper",
  props: {
    id: {
      type: String,
      required: true
    },
    active: {
      type: Boolean,
      required: false,
    },
    props: {
      type: Object
    }
  },
  emits: ['set-active', 'update-position'],
  setup(props, ctx) {
    let isMoving = false
    const styles = computed(() => pick(props.props, ['top', 'left', 'width', 'height']))
    const editWrapperRef = ref<null | HTMLElement>(null)

    const onItemClick = (id: string) => {
      ctx.emit('set-active', id)
    }

    const gap = {x: 0, y: 0}
    const startMove = (e: MouseEvent) => {
      gap.x = e.clientX
      gap.y = e.clientY
      const handleMove = (e: MouseEvent) => {
        const el = editWrapperRef.value
        isMoving = true
        if (el) {
          const {left, top} = {left: el.offsetLeft + e.clientX - gap.x,
            top: el.offsetTop + e.clientY - gap.y}
          gap.x = e.clientX
          gap.y = e.clientY
          el.style.left = `${left}px`
          el.style.top = `${top}px`
        }
      }

      const handleMouseUp = (e: MouseEvent) => {
        document.removeEventListener('mousemove', handleMove)
        const {offsetLeft, offsetTop, offsetWidth, offsetHeight} = editWrapperRef.value as HTMLElement
        if (isMoving) {
          ctx.emit('update-position', {
            left: offsetLeft,
            top: offsetTop,
            width: offsetWidth,
            height: offsetHeight,
            id: props.id
          })
          isMoving = false
        }
        nextTick(() => {
          document.removeEventListener('mouseup', handleMouseUp)
        })
      }
      document.addEventListener('mousemove', handleMove)
      document.addEventListener('mouseup', handleMouseUp)
    }

    const startResize = (direction: string, e: MouseEvent) => {
      gap.x = e.clientX
      gap.y = e.clientY
      const handleMove = (e: MouseEvent) => {
        const el = editWrapperRef.value
        isMoving = true
        if (el) {
          const {width, height} = {width: el.offsetWidth + e.clientX - gap.x,
            height: el.offsetHeight + e.clientY - gap.y}
          gap.x = e.clientX
          gap.y = e.clientY
          el.style.width = `${width}px`
          el.style.height = `${height}px`
        }
      }
      const handleMouseUp = (e: MouseEvent) => {
        document.removeEventListener('mousemove', handleMove)
        if (isMoving) {
          const el = editWrapperRef.value as HTMLElement
          ctx.emit('update-position', {
            left: el.offsetLeft,
            top: el.offsetTop,
            width: el.offsetWidth,
            height: el.offsetHeight,
            id: props.id
          })
          isMoving = false
        }
        nextTick(() => {
          document.removeEventListener('mouseup', handleMouseUp)
        })
      }
      if (direction === 'bottom-right') {
        document.addEventListener('mousemove', handleMove)
        document.addEventListener('mouseup', handleMouseUp)
      }
    }

    const deleteItem = () => {
      console.log('delete')
    }

    return {
      styles,
      editWrapperRef,
      onItemClick,
      startMove,
      startResize,
      deleteItem,
    }
  },
})
</script>

<style scoped>
.edit-wrapper {
  padding: 0;
  cursor: pointer;
  border: 1px solid transparent;
  user-select: none;
  position: absolute;
}
.edit-wrapper.active {
  border: 1px solid #1890ff;
}
.edit-wrapper .resizer-list {
  display: none;
}
.edit-wrapper.active .resizer-list {
  display: block;
}
.edit-wrapper.active .resizer-list .resizer {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fff;
  border: 3px solid #1890ff;
  position: absolute;
}
.edit-wrapper .resizer-list .resizer.top-left {
  left: -5px;
  top: -5px;
  cursor: nwse-resize;
}
.edit-wrapper .resizer-list .resizer.top-right {
  right: -5px;
  top: -5px;
  cursor: nesw-resize;
}
.edit-wrapper .resizer-list .resizer.bottom-left {
  left: -5px;
  bottom: -5px;
  cursor: nesw-resize;
}
.edit-wrapper .resizer-list .resizer.bottom-right {
  right: -5px;
  bottom: -5px;
  cursor: nwse-resize;
}
</style>